Proxy Pattern

Proxy pattern က ကြားခံ တဆင့်ခံပြီး အလုပ်လုပ်သည့် ပုံစံပါ။ UML ကို ကြည့်ကြည့်ပါ။ 

ဥပမာ Database နဲ့ တွဲပြီး ရေးသည့် အခါမှာ Query လုပ်လိုက်တယ်။ Result ပြန်လာတယ်။ ဒါပေမယ့် ကျွန်တော်တို့တွေက cache ထည့်လိုက်ချင်တယ်။ Cache ထည့်ဖို့ အတွက် လက်ရှိ Database code တွေလည်း မထိချင်သည့် အခါမှာ Proxy Pattern ကို အသုံးပြုလို့ ရပါတယ်။

အခု ပုံမှာဆိုရင် Cache ကို Proxy နဲ့ အသုံးပြုလိုက်တာပါ။ လက်ရှိ code တွေကို ထိခိုက်မှု မရှိပဲ cache ထည့်ပြီးသား ဖြစ်သွားပါတယ်။

ထပ်ပြီးတော့ Log ကို ထည့်ဖြည့်မယ်ဆိုတာပါတော့။

Proxy မပါသည့် Class Diagram ကြည့်ရအောင်။

ကျွန်တော်တို့ နောက်ထပ် Performance တိုင်းဖို့ stop watch ထပ်ဖြည့်ချင်ရင် ထပ်ပြီး class ဆောက်ရမယ်။ Application ကို ပြင်ဖို့ လိုပါအုံးမယ်။ အသစ်တွေ ထပ်လာတိုင်း if/else condition တွေ နဲ့ ထပ်ပြီး ပြင်နေရမှာပါ။

Proxy Pattern နဲ့ ဆိုရင် အခု လို ပြောင်းရေးပါမယ်။

အခု အပိုင်းမှာတော့ DatabaseDAO ကို extend လုပ်ပြီး ရေးထားတာ ဖြစ်သည့် အတွက် အသစ်တွေ ထပ်ဖြည့်ရင် လွယ်သွားမှာပါ။

Code ပိုင်းက ပြန်ခေါ်ရင်တော့ ဒီ လို အဆင့်ဆင့် ခေါ်သွားမှာပါ။

Java Code ကို ကြည့်ရအောင်။

Application.java

public class Application {
    public static void main(String[] args) {
        DatabaseDAOImpl db = new DatabaseDAOImpl();
        CacheProxyDatabase cache = new CacheProxyDatabase(db);
        LoggingProxy logProxy = new LoggingProxy(cache);

        logProxy.query();
    }
}

ဒီ code မှာ ဆိုရင် db.query() ကို မခေါ်ပဲ Proxy တွေ ခံပြီး ခေါ်ထားပါတယ်။

Chain Of Responbility လို တစ်ခုပြီး တစ်ခု ခေါ်သွားပါတယ်။ မတူတာကတော့ chain of responbility မှာ next handler နဲ့ သွားပြီး ပြန်ထွက်သွားမယ့် ကိစ္စ ရှိပါတယ်။​

Proxy ကတော့ ကြားခံ သဘောပါပဲ။

DatabaseDAO.java

public interface DatabaseDAO {
    void query();
}

DatabaseDAOImpl.java

public class DatabaseDAOImpl implements DatabaseDAO {
    @Override
    public void query() {
        System.out.println("QUERY");
    }
}

CacheProxyDatabase.java

public class CacheProxyDatabase implements DatabaseDAO{

    DatabaseDAO dao;
    
    CacheProxyDatabase(DatabaseDAO dao) {
        this.dao = dao;
    }
    @Override
    public void query() {
        System.out.println("Cache:: Query from Cache");
        dao.query();
    }
}

LoggingProxy.java

public class LoggingProxy implements DatabaseDAO {

    DatabaseDAO dao;
    LoggingProxy(DatabaseDAO dao) {
        this.dao = dao;
    }
    @Override
    public void query() {
        System.out.println("Log:: Start Query");
        dao.query();
        System.out.println("End:: Start Query");
    }
}

Pros and Cons

Service object ကို client ဘက်က သိဖို့ မလိုပဲ လိုသလို ထိန်းချုပ်ပြောင်းလဲ နိုင်တယ်။

နောက်ပြီးတော့ service တစ်ခု ရဲ့ life cycle ကို client ဘက်က သိဖို့ မလိုပဲ ဖန်တီးနိုင်ပါတယ်။

Open/Closed Principle ကို follow လုပ်ထားသည့် အတွက်ကြောင့် proxy အောက်မှာ ထပ်ပြီး proxy တွေ ခံလို့ရပါတယ်။

မကောင်းတာကတော့ proxy တွေ များသွားရင် နှေးသွားနိုင်တာပါ။

Code ကလည်း trace ပြန်လိုက်သည့် အခါမှာ အဆင့်ဆင့် သွားနေရာလို့ ရှုပ်ထွေးသွားနိုင်ပါတယ်။